package common.controls.tooltips
{
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.InteractiveObject;
	import flash.display.Stage;
	import flash.events.Event;
	import flash.events.MouseEvent;
	import flash.events.TimerEvent;
	import flash.geom.Point;
	import flash.utils.Dictionary;
	import flash.utils.Timer;
	
	import kernel.application.ApplicationDisplay;
	
	/**  
	 * tips
	 * @author carrey
	 * */ 
	public class ToolTips
	{
		public static const MOUSE_CLICK:uint = 1;
		public static const MOUSE_IN:uint = 2;
		private static var transformPoint:Point = new Point();
		
		private var _map:Dictionary;
		private var _showMode:uint;
		private var _target:InteractiveObject;
		private var _display:DisplayObject;
		private var _owner:DisplayObjectContainer;
		private var _renderer:IToolTipsRender;
		private var _stage:Stage;
		private var _continuedTimer:Timer;//继续
		private var _removeTimer:Timer;
		private var _showTimer:Timer;
		
		public function ToolTips(showMode:uint=MOUSE_IN, renderer:IToolTipsRender=null, owner:DisplayObjectContainer=null, showDelay:Number=500, continuedTime:Number=0, removeDelay:Number=0)
		{
			_map = new Dictionary(true);
			_renderer = renderer;
			_owner = owner;
			_showTimer = new Timer(showDelay, 1);
			_continuedTimer = new Timer(continuedTime, 1);
			_removeTimer = new Timer(removeDelay, 1);
			_showTimer.addEventListener(TimerEvent.TIMER_COMPLETE, _showTimerCompleteHandler, false, 0, true);
			_continuedTimer.addEventListener(TimerEvent.TIMER_COMPLETE, _continuedTimerCompleteHandler, false, 0, true);
			_removeTimer.addEventListener(TimerEvent.TIMER_COMPLETE, _removeTimerCompleteHandler, false, 0, true);
		}
		/**
		 *添加显示对象 
		 * @param target
		 * @param data
		 * 
		 */		
		public function addTarget(target:InteractiveObject, data:Object=null):void {
			if (target != null) {
				if (data == null) data = new NullData();
				var value:* = _map[target];
				if (value != null && value != data) this.removeTarget(target);
				_map[target] = data;
				if (_showMode == MOUSE_CLICK) {
					target.addEventListener(MouseEvent.CLICK, _targetReadyShowHandler, false, 0, true);
				} else {
					target.addEventListener(MouseEvent.MOUSE_OVER, _targetReadyShowHandler, false, 0, true);
				}
				target.addEventListener(MouseEvent.MOUSE_OUT, _targetMouseOutHandler, false, 0, true);
			}
		}
		/**
		 * 移出显示对象 
		 * @param target
		 * 
		 */		
		public function removeTarget(target:InteractiveObject):void {
			if (target != null && _map[target] != null) {
				delete _map[target];
				if (_showMode == MOUSE_CLICK) {
					target.removeEventListener(MouseEvent.CLICK, _targetReadyShowHandler);
				} else {
					target.removeEventListener(MouseEvent.MOUSE_OVER, _targetReadyShowHandler);
				}
				target.removeEventListener(MouseEvent.MOUSE_OUT, _targetMouseOutHandler);
				if (_target == target) {
					this.removeDisplay();
					_target = null;
				}
			}
		}
		/**
		 * 清空显示对象数据 
		 * 
		 */		
		public function clear():void {
			var arr:Array = [];
			for (var key:* in _map) {
				arr.push(key);
			}
			for each (key in arr) {
				this.removeTarget(key);
			}
		}
		/**
		 *  鼠标移上或点击
		 * @param e
		 * @param target
		 * 
		 */		
		private function _targetReadyShowHandler(e:MouseEvent, target:InteractiveObject=null):void 
		{
			_removeTimer.reset();
			_continuedTimer.reset();
			_showTimer.reset();
			var target:InteractiveObject = target == null ? e.currentTarget as InteractiveObject : target;
			if (_target != target || _display == null) {
				if (_display != null) _removeDisplay();
				_target = target;
				_showTimer.start();
				//				getView();
			}
		}
		/**
		 * 鼠标移出
		 * @param e
		 * 
		 */		
		private function _targetMouseOutHandler(e:Event):void
		{
			_showTimer.reset();
			var target:InteractiveObject = e.currentTarget as InteractiveObject;
			if (_target == target && _display != null)
			{
				if(_removeTimer.delay == 0) 
				{
					_removeTimerCompleteHandler(null);
				}else{
					_removeTimer.reset();
					_removeTimer.start();
				}
			}else{
				if(_display != null)
				{
					_removeTimer.reset();
					_removeDisplay();
				}
				_target = null;
			}
		}
		
		
		/**
		 *显示tips    view 
		 * @param target
		 * 
		 */		
		public function show(target:InteractiveObject):void {
			if (target != null && _map[target] != null) {
				this.removeDisplay();
				_targetReadyShowHandler(null, target);
			}
		}
		/**
		 *移出tips   view 
		 * @param target
		 * 
		 */		
		public function removeDisplay(target:InteractiveObject=null):void {
			if (target == null) {
				_removeDisplay();
			} else if (_target == target) {
				_removeDisplay();
			}
		}
		private function _removeDisplay():void 
		{
			if (_display != null) {
				_display.removeEventListener(Event.REMOVED_FROM_STAGE, _displayClosingHandler);
				if (_display.parent != null) _display.parent.removeChild(_display);
				_display = null;
			}
		}
		//handlers
		private function _displayClosingHandler(e:Event):void 
		{
			this.removeDisplay();
		}
		private function _displayMouseOutHandler(e:MouseEvent):void
		{
			_showTimer.reset();
			if (_removeTimer.delay == 0) 
			{
				_removeTimerCompleteHandler(null);
			} else {
				_removeTimer.reset();
				_removeTimer.start();
			}
		}
		private function _displayMouseOverHandler(e:MouseEvent):void 
		{
			_removeTimer.reset();
			_showTimer.reset();
		}
		private function _removeTimerCompleteHandler(e:TimerEvent):void 
		{
			_removeTimer.reset();
			_removeDisplay();
			_target = null;
		}
		private function _showTimerCompleteHandler(e:TimerEvent):void 
		{
			if (_renderer == null) 
			{
				_target = null
				return;
			}
			_removeDisplay();
			var data:Object = _map[_target];
			if (data is NullData) data = null;
			_display = _renderer.getDisplayObject(_target, _map[_target]);
			if (_display != null) {
				var owner:DisplayObjectContainer = _owner == null ? ApplicationDisplay.stage : _owner;
				owner.addChild(_display);
				_display.addEventListener(Event.REMOVED_FROM_STAGE, _displayClosingHandler, false, 0, true);
				var io:InteractiveObject = _display as InteractiveObject;
				if (io != null)
				{
					io.addEventListener(MouseEvent.MOUSE_OVER, _displayMouseOverHandler, false, 0, true);
					io.addEventListener(MouseEvent.MOUSE_OUT, _displayMouseOutHandler, false, 0, true);
				}
				if (_continuedTimer.delay>0)
				{
					_continuedTimer.reset();
					_continuedTimer.start();
				}
			}
		}
		private function _continuedTimerCompleteHandler(e:TimerEvent):void
		{
			_removeTimer.reset();
			_removeDisplay();
			_target = null;
		}
		
		/**
		 * 计算坐标
		 * @param dis
		 * @param pos
		 * @param offsetX
		 * @param offsetY
		 * @param owner
		 * 
		 */		
		public static function setDisplayDefaultLocatiion(dis:DisplayObject, pos:Point=null, offsetX:int=5, offsetY:int=5, owner:DisplayObjectContainer=null):void {
			var stage:Stage = ApplicationDisplay.stage;
			var x:Number;
			var y:Number;
			if (pos == null) {
				x = stage.mouseX;
				y = stage.mouseY;
			} else {
				x = pos.x;
				y = pos.y;
			}
			x += offsetX;
			y += offsetY;
			var sw:Number = stage.stageWidth;
			var sh:Number = stage.stageHeight;
			var d:Number = sw-x-dis.width;
			if (d<0) x -= dis.width+10
			d = sh-y-dis.height;
			if (d<0) y -= dis.height+10;
			
			if (owner != null) {
				transformPoint.x = x;
				transformPoint.y = y;
				pos = owner.globalToLocal(transformPoint);
				x = pos.x;
				y = pos.y;
			}
			
			if( x + dis.width > stage.stageWidth )
			{
				x = stage.stageWidth - dis.width;
			}
			if( y + dis.height > stage.stageHeight )
			{
				y = stage.stageHeight - dis.height;
			}
			dis.x = int(x);
			dis.y = int(y);
		}
	}
}
class NullData {
	
}